//-*****************************************************************************
//
// Copyright (c) 2013,
//  Sony Pictures Imageworks Inc. and
//  Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// *       Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// *       Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// *       Neither the name of Sony Pictures Imageworks, nor
// Industrial Light & Magic, nor the names of their contributors may be used
// to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//-*****************************************************************************

#include "OptionsDialog.h"
#include <sstream>

using namespace std;


template <class T>
inline std::string to_string (const T& t)
{
    std::stringstream ss;
    ss << t;
    return ss.str();
}


namespace mariAlembic
{


void MyQDialog::shapesAndMaterialsClicked()
{
    //enable selection in shapes list
    for (int i = 0; i < ui.selectionTreeWidget->topLevelItemCount(); i++)
    {
        QTreeWidgetItem *item =  ui.selectionTreeWidget->topLevelItem ( i );
        Qt::ItemFlags flags = item->flags();
        flags |= Qt::ItemIsEnabled;
        item->setFlags(flags);
    }

    //enable selection in materials list
    for (int i = 0; i < ui.materialList->count(); i++)
    {
        Qt::ItemFlags flags = ui.materialList->item(i)->flags();
        flags |= Qt::ItemIsEnabled;
        ui.materialList->item(i)->setFlags(flags);
    }

}


void MyQDialog::materialsOnlyClicked()
{
    //disable selection in shapes list
    for (int i = 0; i < ui.selectionTreeWidget->topLevelItemCount(); i++)
    {
        QTreeWidgetItem *item =  ui.selectionTreeWidget->topLevelItem ( i );
        Qt::ItemFlags flags = item->flags();
        flags &= ~Qt::ItemIsEnabled;
        item->setFlags(flags);
    }

    //enable selection in materials list
    for (int i = 0; i < ui.materialList->count(); i++)
    {
        Qt::ItemFlags flags = ui.materialList->item(i)->flags();
        flags |= Qt::ItemIsEnabled;
        ui.materialList->item(i)->setFlags(flags);
    }

}


void MyQDialog::shapesOnlyClicked()
{
    // disable selection in the materials list
    for (int i = 0; i < ui.materialList->count(); i++)
    {
        Qt::ItemFlags flags = ui.materialList->item(i)->flags();
        flags &= ~Qt::ItemIsEnabled;
        ui.materialList->item(i)->setFlags(flags);
    }

    // enable selection in shapes list
    for (int i = 0; i < ui.selectionTreeWidget->topLevelItemCount(); i++)
    {
        QTreeWidgetItem *item =  ui.selectionTreeWidget->topLevelItem ( i );
        Qt::ItemFlags flags = item->flags();
        flags |= Qt::ItemIsEnabled;
        item->setFlags(flags);
    }

}


void MyQDialog::updateMaterials(QTreeWidgetItem *, int)
{
    // get selection mode button state here
    if(ui.shapeOnlyRadioButton->isChecked())
    {
        // get selected tree items
        set<string> shapes;
        QList<QTreeWidgetItem *> selected =
            ui.selectionTreeWidget->selectedItems();

        for (int i=0; i< selected.size(); i++)
        {
            QString wName = selected[i]->text(1);
            shapes.insert(wName.toAscii().constData());
        }

        // find the corresponding materials
        set<string> materials;
        map<string, string>::iterator it;
        set<string>::iterator sit;
        for (sit = shapes.begin(); sit!=shapes.end(); sit++)
        {
            it = arData->widgetData->shapeMap.find((*sit));
            if(it!=arData->widgetData->shapeMap.end())
                materials.insert((*it).second);
        }

        // clear material selection
        QListWidgetItem wi;
        ui.materialList->setCurrentItem(&wi, QItemSelectionModel::Clear);

        // select the materials in the materials list
        for (int i = 0; i < ui.materialList->count(); i++)
        {
            sit = materials.find(
                ui.materialList->item(i)->text().toStdString());
            if (sit != materials.end())
            {
                ui.materialList->item(i)->setSelected(true);
            }
        }
    }

}


void MyQDialog::updateShapes(QListWidgetItem *)
{
    // get selection mode button state here
    if(ui.materialOnlyRadioButton->isChecked())
    {
        // get selected material items
        set<string> materials;
        QList<QListWidgetItem *> selected = ui.materialList->selectedItems();
        for (int i=0; i< selected.size(); i++)
        {
            QString wName = selected[i]->text();
            materials.insert(wName.toAscii().constData());
        }

        // find the corresponding shapes
        set<string> shapes;
        set<string>::iterator it;
        map<string, set<string> >::iterator mit;
        set<string>::iterator sit;
        for (it=materials.begin(); it!=materials.end(); it++)
        {
            mit = arData->widgetData->materialMap.find((*it));
            if(mit!=arData->widgetData->materialMap.end())
            {
                for (sit=(*mit).second.begin(); sit!=(*mit).second.end(); sit++)
                {
                    shapes.insert((*sit));
                }
            }
        }

        // clear shapes selection
        QTreeWidgetItem wi;
        ui.selectionTreeWidget->setCurrentItem(&wi, QItemSelectionModel::Clear);

        // select the shapes in the shapes list
        QTreeWidgetItemIterator it2(ui.selectionTreeWidget);
        while (*it2)
        {
            sit = shapes.find((*it2)->text(1).toStdString());
            if (sit != shapes.end())
            {
                (*it2)->setSelected(true);
            }

            ++it2;
        }
    }

}


MyQDialog::MyQDialog(AlembicReader *data)
{
    arData = data;

    ui.setupUi(this);

    connect(ui.selectionTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
        this, SLOT(updateMaterials(QTreeWidgetItem *, int)));

    connect(ui.materialList, SIGNAL(itemClicked(QListWidgetItem *)),
        this, SLOT(updateShapes(QListWidgetItem *)));

    connect(ui.shapeOnlyRadioButton, SIGNAL(clicked()),
        this, SLOT(shapesOnlyClicked()));

    connect(ui.materialOnlyRadioButton, SIGNAL(clicked()),
        this, SLOT(materialsOnlyClicked()));

    connect(ui.shapeAndMaterialRadioButton, SIGNAL(clicked()),
        this, SLOT(shapesAndMaterialsClicked()));

}


bool OptionsDialog::addChildren(TreeEntry *parent, QTreeWidgetItem *wItem)
{

    for(unsigned int i=0; i<parent->children.size(); i++)
    {
        QTreeWidgetItem *childItem = new QTreeWidgetItem(wItem);
        childItem->setText(0, parent->children[i]->shortName.c_str());
        childItem->setText(1, parent->children[i]->fullName.c_str());
        addChildren(parent->children[i], childItem);
        childItem->setExpanded(true);
    }

    return true;
}


bool OptionsDialog::createTree(TreeEntry &root, QTreeWidget *rootWidget)
{
    for(unsigned int i=0; i<root.children.size(); i++)
    {
        QTreeWidgetItem *wItem = new QTreeWidgetItem(rootWidget);
        wItem->setText(0, root.children[i]->shortName.c_str());
        wItem->setText(1, root.children[i]->fullName.c_str());
        addChildren(root.children[i], wItem);
        wItem->setExpanded(true);
    }

    return true;
}


bool OptionsDialog::createMaterialList(map<string, set<string> > &materialMap,
    QListWidget *rootList)
{
    map<string, set<string> >::iterator it;
    for(it=materialMap.begin(); it!= materialMap.end(); it++)
    {
        QListWidgetItem *lItem = new QListWidgetItem(rootList);
        QString qstr((*it).first.c_str());
        lItem->setText(qstr);
    }

    return true;
}




}



